/*******************************************************************

    Author: Xiao
    Date: 2022/3/28 15:18

*******************************************************************/
package middleware

import (
	"fmt"
	"mcr/pkg/config"
	"mcr/pkg/dao"
	"mcr/pkg/logs"
	"time"

	"github.com/dgrijalva/jwt-go"
)

// 私钥
var jwtKey = []byte(config.ConfigValue.AesKey)

// 获取token信息
func CreateToken(userName, plat string, userId int, expireDuration time.Duration) (string, error) {
	// 将 uid，用户角色， 过期时间作为数据写入 token 中
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		// 自定义的字段，用于之后用户信息的获取
		"UserName": userName,
		"UserId":   userId,
		"Plat":     plat,
		//系统提供的字段
		//token签发日期
		"iat": time.Now().Unix(),
		// token过期日期
		"exp": time.Now().Add(expireDuration).Unix(),
	})
	// SecretKey 用于对用户数据进行签名，不能暴露
	return token.SignedString(jwtKey)
}

// 签名
type Claims struct {
	UserName string
	UserId   int
	Plat     string
	//系统提供的字段
	jwt.StandardClaims
}

// 解析token
func parseToken(tokenStr string) (*jwt.Token, *Claims, error) {
	claims := &Claims{}
	//extractedToken := strings.Split(tokenStr, "Bearer ")
	//if len(extractedToken) != 2 {
	//	errMsg := fmt.Sprintf("无效Token:%s",extractedToken)
	//	logs.Log.Error(errMsg)
	//	return nil,nil, errors.New(errMsg)
	//}
	//tokenString := extractedToken[1]
	token, err := jwt.ParseWithClaims(tokenStr, claims, func(token *jwt.Token) (i interface{}, e error) {
		return jwtKey, nil
	})
	return token, claims, err
}

// 从jwt中获取用户名
func GetUsername(token string) (string, error) {
	_, claim, err := parseToken(token)
	if claim != nil && err == nil {
		return claim.UserName, err
	}
	return "", fmt.Errorf("用户签名不存在")
}

// 从jwt中获取用户ID
func GetUserId(token string) (int, error) {
	_, claim, err := parseToken(token)
	if claim != nil && err == nil {
		return claim.UserId, err
	}
	return 0, fmt.Errorf("用户签名不存在")
}

// 判断用户权限
func CheckJwtAuth(str string) (bool, string) {
	token, claims, err := parseToken(str)
	if err == nil && token.Valid {
		oldToken, err := dao.GetToken(claims.UserName + "(" + claims.Plat + ")")
		if err != nil {
			logs.Log.Errorf("获取token信息失败:%s", err)
			return false, "鉴权失败,请重新登录"
		}
		if oldToken == token.Raw {
			status, err := dao.GetUserStatusById(claims.UserId)
			if err != nil {
				return false, "鉴权失败,请重新登录"
			}
			if status == 1 {
				return false, "你的账户已被禁用"
			}
			return true, ""
		}
	}
	if err != nil {
		logs.Log.Errorf("解析JWT错误:%s", err)
		return false, "鉴权失败,请重新登录"
	}
	return false, "身份已过期,请重新登录"
}
